package com.powernode.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.powernode.constant.BusinessEnum;
import com.powernode.constant.StoreConstants;
import com.powernode.domain.IndexImg;
import com.powernode.domain.Prod;
import com.powernode.ex.handler.BusinessException;
import com.powernode.feign.StoreProdFeign;
import com.powernode.mapper.IndexImgMapper;
import com.powernode.model.Result;
import com.powernode.service.IndexImgService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;

@Service
@CacheConfig(cacheNames = "com.powernode.service.impl.IndexImgServiceImpl")
public class IndexImgServiceImpl extends ServiceImpl<IndexImgMapper, IndexImg> implements IndexImgService {

    @Autowired
    private IndexImgMapper indexImgMapper;

    @Autowired
    StoreProdFeign storeProdFeign;

    /**
     * 保存首页图片信息
     * <p>
     * 此方法主要用于保存首页图片的信息它首先设置了一些特定的字段值，
     * 如商店ID和创建时间，并根据类型值决定产品ID的设置然后将该信息插入数据库
     *
     * @param indexImg 要保存的首页图片对象，包含图片的相关信息
     * @return 返回一个布尔值，表示图片信息是否成功插入数据库
     */
    @Override
    @CacheEvict(key = StoreConstants.WX_INDEX_IMG_KEY)
    public Boolean saveIndexImg(IndexImg indexImg) {
        // 设置图片对应的商店ID为1
        indexImg.setShopId(1L);
        // 设置图片的创建时间为当前时间
        indexImg.setCreateTime(new Date());
        // 如果图片类型为-1，则设置产品ID为null
        if (-1 == indexImg.getType()) {
            indexImg.setProdId(null);
        }
        // 调用Mapper的insert方法插入图片信息，并判断插入是否成功
        return indexImgMapper.insert(indexImg) > 0;
    }

    /**
     * 根据图片ID查询首页图片信息
     * 此方法首先通过图片ID从数据库中查询首页图片对象，然后根据图片类型决定是否需要从商店产品服务中获取额外信息
     * 如果图片类型为0，表示需要从商店产品服务中获取产品信息，并将相关信息设置到首页图片对象中
     *
     * @param imgId 首页图片的唯一标识符
     * @return 返回包含首页图片信息的IndexImg对象
     * @throws BusinessException 如果从商店产品服务中获取产品信息失败，则抛出业务异常
     */
    @Override
    @CacheEvict(key = StoreConstants.WX_INDEX_IMG_KEY)
    public IndexImg queryIndexImgInfoById(Long imgId) {
        // 根据标识查询轮播图信息
        IndexImg indexImg = indexImgMapper.selectById(imgId);
        // 获取轮播图关联类型
        Integer type = indexImg.getType();
        // 判断是否有值
        if (0 == type) {
            // 说明：当前轮播图已关联商品
            // 获取关联商品的id
            Long prodId = indexImg.getProdId();
            // 远程调用：根据商品标识查询商品信息
            Result<List<Prod>> result = storeProdFeign.getProdListByIds(Arrays.asList(prodId));
            // 判断是否成功
            if (result.getCode().equals(BusinessEnum.OPERATION_FAIL.getCode())) {
                throw new BusinessException(result.getMsg());
            }
            // 获取远程调用接口的数据
            List<Prod> prodList = result.getData();
            // 获取商品对象
            Prod prod = prodList.get(0);

            indexImg.setProdName(prod.getProdName());
            indexImg.setPic(prod.getPic());
        }

        return indexImg;
    }

    /**
     * 修改首页图片
     * <p>
     * 该方法用于更新首页图片信息，确保在数据库中正确更新
     * 它使用了Spring的事务管理，确保在出现异常时回滚事务
     * 此外，它还会清除缓存中的首页图片信息，以保持数据一致性
     *
     * @param indexImg 要修改的首页图片对象，包含要更新的信息
     * @return 返回一个布尔值，表示是否成功更新了首页图片信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(key = StoreConstants.WX_INDEX_IMG_KEY)
    public Boolean modifyIndexImg(IndexImg indexImg) {
        // 检查首页图片的类型，如果类型为-1，或者类型为0且商品ID为空，则将类型设置为-1，商品ID设置为空
        // 这是为了处理特定的业务逻辑，确保数据的一致性和有效性
        Integer type = indexImg.getType();
        if (-1 == type || (0 == type && ObjectUtil.isNull(indexImg.getProdId()))) {
            indexImg.setType(-1);
            indexImg.setProdId(null);
        }

        // 调用MyBatis-Plus的updateById方法，根据ID更新首页图片信息
        // 这里不需要额外的注释，因为updateById方法的作用和使用方式是MyBatis-Plus框架提供的，对于开发者来说是已知的
        return updateById(indexImg);
    }

    /**
     * 根据图片ID列表移除轮播图图片
     *
     * @param imgIds 图片ID列表，用于指定需要移除的图片
     * @return 如果所有指定的图片都成功移除，则返回true；否则返回false
     */
    @Override
    @CacheEvict(key = StoreConstants.WX_INDEX_IMG_KEY)
    public Boolean removeIndexImgByIds(List<Long> imgIds) {
        // 判断删除操作的影响行数是否与传入的图片ID数量相等，以确认所有图片都被成功删除
        return indexImgMapper.deleteBatchIds(imgIds) == imgIds.size();
    }

    /**
     * 查询微信首页图片列表
     *
     * @return 返回微信首页图片列表
     *
     * @Cacheable 注解表示该方法的返回值会被缓存起来，下次调用时直接从缓存中获取结果，而不是重新执行方法。
     * key = StoreConstants.WX_INDEX_IMG_KEY 指定了缓存的键名，即缓存的唯一标识。
     */
// 重写queryWxIndexImgList方法
    @Override
    // 使用缓存注解，当查询结果被缓存后，后续相同的查询将直接从缓存中获取数据，而不是再次执行该方法
    @Cacheable(key = StoreConstants.WX_INDEX_IMG_KEY)
    public List<IndexImg> queryWxIndexImgList() {
        // 使用Lambda表达式构建查询条件，查询状态为1（假设1代表有效）的IndexImg记录，并按seq字段降序排列
        return indexImgMapper.selectList(new LambdaQueryWrapper<IndexImg>().eq(IndexImg::getStatus, 1).orderByDesc(IndexImg::getSeq));
    }


}
